package com.gitee.wsl.common.chart.sample.rangebar

import android.graphics.Canvas
import android.graphics.Paint
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.chart.adapter.DataSource
import com.gitee.wsl.common.chart.adapter.SelectItemChartAdapter
import com.gitee.wsl.common.chart.listener.click.BarPosition
import com.gitee.wsl.common.chart.listener.click.PlotBarPosition
import com.gitee.wsl.common.chart.render.background.axis.line.CategoryLineAxis
import com.gitee.wsl.common.chart.render.background.axis.line.DataLineAxis
import com.gitee.wsl.common.chart.render.shape.bar.Bar
import com.gitee.wsl.common.chart.render.shape.bar.FlatBar
import com.gitee.wsl.common.chart.sample.AbstractAxesChart
import com.gitee.wsl.common.chart.sample.rangebar.adapter.RangeBarChartAdapter
import com.gitee.wsl.common.chart.sample.rangebar.model.RangeBarData
import com.gitee.wsl.common.ui.draw.type.GridDirection
import com.gitee.wsl.common.ui.draw.type.VerticalAlign
import com.gitee.wsl.android.ui.ext.type.textHeight
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.mul
import com.gitee.wsl.jvm.math.sub

import timber.log.Timber


/**
 * @ClassName RangeBarChart
 * @Description  范围柱形图的基类
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 *
 */
class RangeBarChart(val adapter: RangeBarChartAdapter = RangeBarChartAdapter()) :
    AbstractAxesChart(adapter),
    SelectItemChartAdapter<RangeBarData> by adapter {

    //数据源
    var dataSet by DataSource(adapter)

    // 柱形基类
    val flatBar = FlatBar()

    var key = ""
    var barWidth = 50f

    var labelVisible = true


    //分类轴的最大，最小值
    var maxCategoryAxisValue = 0.0
    var minCategoryAxisValue = 0.0


    override fun getType(): ChartEnum.ChartType {
        return ChartEnum.ChartType.RANGEBAR
    }

    /**
     * 开放柱形绘制类
     * @return 柱形绘制类
     */
    fun getBar(): Bar {
        return flatBar
    }


    override fun categoryAxisDefaultSetting(categoryAxis: CategoryLineAxis) {
        super.categoryAxisDefaultSetting(categoryAxis)
        when (chartDirection) {
            ChartEnum.ChartDirection.HORIZONTAL -> {
                categoryAxis.tickMarksAlign = Paint.Align.LEFT
                categoryAxis.tickMarkPaint.textAlign = Paint.Align.RIGHT
                categoryAxis.tickMarksPosition = VerticalAlign.MIDDLE
                categoryAxisLocation = ChartEnum.AxisLocation.LEFT
            }

            ChartEnum.ChartDirection.VERTICAL -> {
                categoryAxis.tickMarksAlign = Paint.Align.CENTER
                categoryAxis.tickMarkPaint.textAlign = Paint.Align.CENTER
                categoryAxis.tickMarksPosition = VerticalAlign.BOTTOM
                categoryAxisLocation = ChartEnum.AxisLocation.BOTTOM
            }
        }
    }


    override fun dataAxisDefaultSetting(dataAxis: DataLineAxis) {
        super.dataAxisDefaultSetting(dataAxis)
        when (chartDirection) {
            ChartEnum.ChartDirection.HORIZONTAL -> {
                dataAxis.tickMarksAlign = Paint.Align.CENTER
                dataAxis.tickMarkPaint.textAlign = Paint.Align.CENTER
                dataAxis.tickMarksPosition = VerticalAlign.BOTTOM
                dataAxisLocation = ChartEnum.AxisLocation.BOTTOM
            }

            ChartEnum.ChartDirection.VERTICAL -> {
                dataAxis.tickMarksAlign = Paint.Align.LEFT
                dataAxis.tickMarkPaint.textAlign = Paint.Align.RIGHT
                dataAxis.tickMarksPosition = (VerticalAlign.MIDDLE)
                dataAxisLocation = ChartEnum.AxisLocation.LEFT
            }
        }
    }

    private fun cataPosition(min: Float, max: Float, dataAxis: DataLineAxis): FloatArray {
        val pos = FloatArray(2)
        val axisDataHeight: Float = dataAxis.axisRange
        val scrHeight = getAxisScreenHeight()
        var t = Math.sub(min, dataAxis.axisMin)
        pos[0] = Math.mul(scrHeight, Math.div(t, axisDataHeight))
        t = Math.sub(max, dataAxis.axisMin)
        pos[1] = Math.mul(scrHeight, Math.div(t, axisDataHeight))
        return pos
    }


    /**
     * 绘制竖向柱形图
     */
    protected fun drawVerticalBar(
        canvas: Canvas,
        dataAxis: DataLineAxis,
        categoryAxis: CategoryLineAxis
    ): Boolean {

        //检查是否有设置分类轴的最大最小值		
        if (maxCategoryAxisValue == minCategoryAxisValue && 0.0 == maxCategoryAxisValue) {
            Timber.d("请检查是否有设置分类轴的最大最小值。")
            return false
        }


        // 得到分类轴数据集
        val dataSet: List<String> = categoryAxis.dataSet

        // 得到分类轴数据集
        val cateDataSet: List<String> = categoryAxis.dataSet

        //float XSteps = getVerticalXSteps(cateDataSet.size() + 1 );	
        var currentX = 0.0f
        var barMaxPos = 0.0f
        var barMinPos = 0.0f
        val barWidthHalf = barWidth / 2
        val axisScreenWidth = getPlotScreenWidth()
        val fontHeight = flatBar.itemLabelPaint.textHeight


        // X 轴 即分类轴
        val dataSetSize = this.dataSet.size
        for (i in 0 until dataSetSize) {
            // 得到分类对应的值数据集
            val bd = this.dataSet[i]
            //currentX = add(plotArea.left , mul( (i+1) , XSteps));
            //
            currentX = (axisScreenWidth * ((bd.x - minCategoryAxisValue) / (maxCategoryAxisValue - minCategoryAxisValue))).toFloat()
            currentX += bodyViewport.left
            val pos = cataPosition(bd.min, bd.max, dataAxis)
            barMaxPos = Math.sub(bodyViewport.bottom, pos[0])
            barMinPos = Math.sub(bodyViewport.bottom, pos[1])
            flatBar.renderBar(
                currentX - barWidthHalf, barMaxPos,
                currentX + barWidthHalf, barMinPos,
                canvas
            )
            //保存位置
            saveBarRectFRecord(
                i, 0, currentX - barWidthHalf + moveX, barMaxPos + moveY,
                currentX + barWidthHalf + moveX, barMinPos + moveY
            )

            //显示焦点框
            drawFocusRect(
                canvas, i, 0, currentX - barWidthHalf, barMaxPos,
                currentX + barWidthHalf, barMinPos
            )
            if (labelVisible) {
                //柱形标签
                flatBar.renderBarItemLabel(
                    getFormatterItemLabel(bd.max),
                    currentX, barMinPos - fontHeight / 2, canvas
                )

                //柱形标签
                flatBar.renderBarItemLabel(
                    getFormatterItemLabel(bd.min),
                    currentX, barMaxPos + fontHeight + fontHeight / 2, canvas
                )
            }
        }
        adapter.isRecordSetInited = true
        return true
    }

    fun saveBarRectFRecord(
        dataID: Int, childID: Int, left: Float,
        top: Float, right: Float, bottom: Float
    ) {
        if (adapter.isRecordSetInited) return
        val pRecord = PlotBarPosition()
        pRecord.savePlotDataID(dataID)
        pRecord.savePlotDataChildID(childID)
        pRecord.savePlotRectF(left, top, right, bottom)
        //pRecord.extPointClickRange(clickRangeExtValue)
        adapter.addRecordItem(pRecord)
    }
	

    /**
     * 返回当前点击点的信息
     * @param x 点击点X坐标
     * @param y    点击点Y坐标
     * @return 返回对应的位置记录
     */
    fun getPositionRecord(x: Float, y: Float): BarPosition? {
        return selectHelper?.getBarRecord(x, y)
    }

    override fun drawClipDataAxisGridlines(
        canvas: Canvas,
        dataAxis: DataLineAxis,
        pos: ChartEnum.AxisLocation
    ) {

        // 数据轴数据刻度总个数
        val tickCount: Int = dataAxis.axisTickCount
        var labeltickCount = tickCount
        if (0 == tickCount) {
            Timber.d("数据库数据源为0!")
            return
        } else if (1 == tickCount) //label仅一个时右移
            labeltickCount = 0


        // 与柱形图不同，无须多弄一个
        var XSteps = 0.0f
        var YSteps = 0.0f

        // 标签轴(X 轴)
        var axisX = 0.0f
        var axisY = 0.0f
        var currentX = 0.0f
        var currentY = 0.0f
        // 标签
        var currentTickLabel = 0.0f
        // 轴位置
        //val pos: ChartEnum.AxisLocation = getDataAxisLocation()
        when (pos) {
            ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER -> {
                YSteps = getVerticalYSteps(labeltickCount)
                run {
                    axisX = getAxisXPos(pos)
                    currentX = axisX
                }
                run {
                    axisY = bodyViewport.bottom
                    currentY = axisY
                }
            }

            ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER -> {
                XSteps = getVerticalXSteps(labeltickCount)
                run {
                    axisY = getAxisYPos(pos)
                    currentY = axisY
                }
                run {
                    axisX = bodyViewport.left
                    currentX = axisX
                }
            }
        }

        plotGrid.drawClipDataAxisGridlines(canvas, dataAxis, bodyViewport, XSteps, YSteps, axisX, axisY, tickCount, pos,false)

        /*lstDataTick.clear()
        //绘制
        for (i in 0 until tickCount) {
            when (pos) {
                ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER -> {
                    // 依起始数据坐标与数据刻度间距算出上移高度
                    currentY = sub(bodyViewport.bottom, mul(i.toFloat(), YSteps))

                    // 从左到右的横向网格线
                    plotGrid.renderHorizontalGridLines(canvas, false, bodyViewport.left, bodyViewport.right, i, tickCount, YSteps, currentY)

                    //if(!dataAxis.isShowAxisLabels())continue;

                    // 标签					
                    currentTickLabel = add(dataAxis.axisMin, i * dataAxis.axisSteps)
                    lstDataTick.add(PlotAxisTick(i, axisX, currentY, currentTickLabel.toString()))
                }

                ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER -> {
                    //bar
                    // 依起始数据坐标与数据刻度间距算出上移高度
                    currentX = add(axisX, mul(i.toFloat(), XSteps))

                    //绘制竖向网格线
                    plotGrid.renderVerticalGridLines(canvas, bodyViewport.top, bodyViewport.bottom, i, tickCount, XSteps, currentX)

                    // if(!dataAxis.isShowAxisLabels())continue;

                    // 画上标签/刻度线	
                    currentTickLabel = add(dataAxis.axisMin, i * dataAxis.axisSteps)
                    lstDataTick.add(PlotAxisTick(i, currentX, axisY, currentTickLabel.toString()))
                }
            }
        } //end for*/
    }


    /**
     * 绘制底部标签轴
     */
    override fun drawClipCategoryAxisGridlines(
        canvas: Canvas,
        categoryAxis: CategoryLineAxis,
        pos: ChartEnum.AxisLocation
    ) {
        // 得到标签轴数据集
        val dataSet: List<String> = categoryAxis.dataSet
        val tickCount = dataSet.size
        val labeltickCount = tickCount + 1
        if (0 == tickCount) {
            Timber.d("分类轴数据源为0!")
            return
        }
        // 与柱形图不同，无须多弄一个
        var XSteps = 0.0f
        var YSteps = 0.0f

        // 标签轴(X 轴)
        var axisX = 0.0f
        var axisY = 0.0f

        //val pos: ChartEnum.AxisLocation = getCategoryAxisLocation()
        if (ChartEnum.AxisLocation.LEFT == pos || ChartEnum.AxisLocation.RIGHT == pos || ChartEnum.AxisLocation.VERTICAL_CENTER == pos) {
            //line
            YSteps = getVerticalYSteps(labeltickCount)
            axisX = getAxisXPos(pos)
            axisY = bodyViewport.bottom
        } else { //TOP BOTTOM																	
            // 依传入的分类个数与轴总宽度算出要画的分类间距数是多少
            // 总宽度 / 分类个数 = 间距长度    //getAxisScreenWidth() 			
            XSteps = getVerticalXSteps(labeltickCount)
            axisY = getAxisYPos(pos)
            axisX = bodyViewport.left
        }

        plotGrid.drawClipCategoryAxisGridlines(canvas, categoryAxis, bodyViewport, XSteps, YSteps, axisX, axisY, tickCount)
    }

    override fun drawClipPlot(
        canvas: Canvas,
        dataAxis: DataLineAxis,
        categoryAxis: CategoryLineAxis
    ) {
        when (gridDirection) {
            GridDirection.HORIZONTAL -> {}
            GridDirection.VERTICAL -> drawVerticalBar(canvas, dataAxis, categoryAxis)
        }
    }


    protected override fun drawClipLegend(canvas: Canvas) {
        // 绘制柱形图例
        //plotLegend.renderRangeBarKey(canvas, getKey(), mFlatBar.barPaint.color)
    }
    ////////////////////////
}